#include <QtCore/QCoreApplication>
#include <QVBoxLayout>
#include "mainwindow.h"
#include "loader.h"
#include "inputarea.h"
#include "navdatahandler.h"
#include "atcommand.h"
#include "navdata.h"
#include "settings.h"

#ifdef USE_VIDEO_PROCESSOR
#include "videoprocessor.h"
#endif

/*!
    Constructs the \c MainWindow.
    The \a parent parameter is sent to the QMainWindow constructor.
*/
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    qDebug() << "[ARDrone] Constructor";
    mNoConnectionExit = true;
    mCentralWidget = new QWidget(this);
    mCentralWidget->setAttribute(Qt::WA_AcceptTouchEvents, true);
    mVerticalLayoutMain = new QVBoxLayout(mCentralWidget);
    mVerticalLayoutMain->setSpacing(0);
    mVerticalLayoutMain->setContentsMargins(0, 0, 0, 0);
    mVerticalLayoutMain->setObjectName(QString::fromUtf8("verticalLayoutMain"));

#ifndef NO_DRONE_CONNECTION
    mLoader = new Loader(this);
    setCentralWidget(mLoader);
    connect(mLoader, SIGNAL(noDroneConnection()), this, SLOT(noDroneConnection()));
    connect(mLoader, SIGNAL(droneConnected(QString)), this, SLOT(droneConnected(QString)));
#else
    droneConnected("0.0.0");
#endif
}

/*!
    Destructor.
*/
MainWindow::~MainWindow()
{
    qDebug() << "[ARDrone] Destructor";
    // If we are exiting before we got a connection to the drone then the following components will
    // not have been loaded yet.
    if (!mNoConnectionExit) {
        delete mNavDataHandler;
        delete mAtCommand;
#ifdef USE_VIDEO_PROCESSOR
        delete mVideoProcessor;
#endif
    }
}

/*!
    This function is used to lock the app orientation to landscape.
*/
void MainWindow::setOrientation(ScreenOrientation orientation)
{
#if defined(Q_OS_SYMBIAN)
    // If the version of Qt on the device is < 4.7.2, that attribute won't work
    if (orientation != ScreenOrientationAuto) {
        const QStringList v = QString::fromAscii(qVersion()).split(QLatin1Char('.'));
        if (v.count() == 3 && (v.at(0).toInt() << 16 | v.at(1).toInt() << 8 | v.at(2).toInt()) < 0x040702) {
            qWarning("Screen orientation locking only supported with Qt 4.7.2 and above");
            return;
        }
    }
#endif // Q_OS_SYMBIAN

    Qt::WidgetAttribute attribute;
    switch (orientation) {
#if QT_VERSION < 0x040702
    // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes
    case ScreenOrientationLockPortrait:
        attribute = static_cast<Qt::WidgetAttribute>(128);
        break;
    case ScreenOrientationLockLandscape:
        attribute = static_cast<Qt::WidgetAttribute>(129);
        break;
    default:
    case ScreenOrientationAuto:
        attribute = static_cast<Qt::WidgetAttribute>(130);
        break;
#else // QT_VERSION < 0x040702
    case ScreenOrientationLockPortrait:
        attribute = Qt::WA_LockPortraitOrientation;
        break;
    case ScreenOrientationLockLandscape:
        attribute = Qt::WA_LockLandscapeOrientation;
        break;
    default:
    case ScreenOrientationAuto:
        attribute = Qt::WA_AutoOrientation;
        break;
#endif // QT_VERSION < 0x040702
    };
    setAttribute(attribute, true);
}

/*!
    This function will show the app in fullscreen.
*/
void MainWindow::showExpanded()
{
#if defined(Q_OS_SYMBIAN) || defined(Q_WS_SIMULATOR)
    showFullScreen();
#elif defined(Q_WS_MAEMO_5)
    showMaximized();
#else
    show();
#endif
}

/*!
    Slot that will load all the different components and set up signals between them once the
        Loader signals that connection to the drone has been confirmed.
*/
void MainWindow::droneConnected(QString version)
{
    qDebug() << "[ARDrone] Connected to drone. Firmware version: " << version;

    QStringList versionSplit;
    versionSplit = version.split(".");
    int firmwareVersion = -1;
    if (versionSplit[1].toInt() < 5) {
        firmwareVersion = FW_147;
    } else {
        firmwareVersion = FW_151;
    }

    setCentralWidget(mCentralWidget);

    mInputArea = new InputArea(this);
    mVerticalLayoutMain->addWidget(mInputArea);

    mSettings = new Settings(this);
    mSettings->hide();
    mSettings->setFirmwareVersion(version);
    mVerticalLayoutMain->addWidget(mSettings);

    mNavDataHandler = new NavDataHandler(firmwareVersion);
    mAtCommand = new AtCommand(firmwareVersion);

#ifdef USE_VIDEO_PROCESSOR
    mVideoProcessor = new VideoProcessor();
    qRegisterMetaType<QImage>("QImage");
    connect(mVideoProcessor, SIGNAL(newImageProcessed(QImage)),
            mInputArea, SLOT(recieveVideoImage(QImage)));
#endif

    connect(mSettings, SIGNAL(back()), this, SLOT(settingsBack()));

    connect(mNavDataHandler, SIGNAL(updateARDroneState(uint)),
            mAtCommand, SLOT(updateARDroneState(uint)));
    connect(mNavDataHandler, SIGNAL(sendInitSequence(int)),
            mAtCommand, SLOT(sendInitSequence(int)));
    connect(mNavDataHandler, SIGNAL(updateBatteryLevel(uint)),
            mInputArea, SLOT(updateBatteryLevel(uint)));
    connect(mNavDataHandler, SIGNAL(updateEmergencyState(bool)),
            mInputArea, SLOT(updateEmergencyState(bool)));

    connect(mInputArea, SIGNAL(settingsPressed()), this, SLOT(showSettings()));
    connect(mInputArea, SIGNAL(emergencyPressed()), mAtCommand, SLOT(emergencyPressed()));
    connect(mInputArea, SIGNAL(resetPressed()), mAtCommand, SLOT(resetPressed()));
    connect(mInputArea, SIGNAL(startPressed()), mAtCommand, SLOT(startPressed()));
    connect(mInputArea, SIGNAL(stopPressed()), mAtCommand, SLOT(stopPressed()));
    connect(mInputArea, SIGNAL(cameraPressed()), mAtCommand, SLOT(changeCamera()));
    connect(mInputArea, SIGNAL(dataChange(qreal,qreal)), mAtCommand, SLOT(setData(qreal,qreal)));
    connect(mInputArea, SIGNAL(accelPressed()), mAtCommand, SLOT(accelPressed()));
    connect(mInputArea, SIGNAL(accelReleased()), mAtCommand, SLOT(accelReleased()));

    mSettings->loadSettings();

    mNoConnectionExit = false;

#ifdef NO_DRONE_CONNECTION
    // Updating the battery level will make the UI visible.
    mInputArea->updateBatteryLevel(0);
#endif
}

/*!
    Slot called from the Loader in case it could not connect to the drone.
*/
void MainWindow::noDroneConnection()
{
    this->close();
}

void MainWindow::settingsBack()
{
    mInputArea->show();
    mSettings->hide();
}

void MainWindow::showSettings()
{
    mSettings->show();
    mInputArea->hide();
}

